package com.haixiaoke.saas.repository.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.haixiaoke.saas.repository.core.AjaxResult;
import com.haixiaoke.saas.repository.exception.BizException;
import com.haixiaoke.saas.repository.mapper.HouseFacilitiesItemMapper;
import com.haixiaoke.saas.repository.mapper.HouseInspectionFacilityMapper;
import com.haixiaoke.saas.repository.pojo.*;
import com.haixiaoke.saas.repository.service.*;
import com.haixiaoke.saas.repository.util.GsonUtil;
import com.mzj.saas.commons.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 房管家Service业务层处理
 *
 * @author qixi
 * @date 2023-04-14
 */
@Service
@Slf4j
public class HouseKeeperServiceImpl implements IHouseKeeperService {

    @Autowired
    private IOrderService orderService;
    @Autowired
    private IOrderOperatingRecordService orderOperatingRecordService;
    @Autowired
    private HouseFacilitiesItemMapper houseFacilitiesItemMapper;
    @Autowired
    private HouseInspectionFacilityMapper houseInspectionFacilityMapper;
    @Autowired
    private IHouseQuitLeaseService houseQuitLeaseService;
    @Autowired
    private IHouseInspectionService houseInspectionService;
    @Autowired
    private ISubscribeService subscribeService;
    @Autowired
    private IHousingAllocationService housingAllocationService;
    @Autowired
    private IApartmentBillRuleService apartmentBillRuleService;
    @Autowired
    private IApartmentChargeItemService apartmentChargeItemService;
    @Autowired
    private IApartmentItemRuleRefService apartmentItemRuleRefService;
    @Autowired
    private IPayTypeService payTypeService;
    @Autowired
    private ApartmentBillServiceImpl apartmentBillService;


    /**
     * 办理入住
     *
     * @param orderId 订单id
     * @return 临时密码
     */
    @Override
    public AjaxResult toStayIn(String orderId) {
        Order order = orderService.selectOrderById(orderId);
        Date date = new Date();
        // 新增订单操作记录
        OrderOperatingRecord orderRecord = new OrderOperatingRecord();
        orderRecord.setOrderId(order.getOrderId());
        orderRecord.setOrderSourceState(order.getOrderState());
        orderRecord.setOrderState(Order.ORDER_STATE_CHECK_IN);
        orderRecord.setCreateBy("System");
        orderRecord.setCreateTime(date);
        orderRecord.setOperatingBy("System");
        orderRecord.setOperatingTime(date);

        order.setOrderState(Order.ORDER_STATE_UN_INSPECTION);
        order.setRealityCheckInTime(date);
        orderService.updateOrder(order);
        orderOperatingRecordService.insertOrderOperatingRecord(orderRecord);


        // 新增验房设施 20230417 xiaolnog
        HouseFacilitiesItem houseFacilitiesItem = new HouseFacilitiesItem();
        houseFacilitiesItem.setHouseId(order.getHouseId());
        List<HouseFacilitiesItem> houseFacilitiesItems = houseFacilitiesItemMapper.selectHouseFacilitiesItemList(houseFacilitiesItem);
        for (HouseFacilitiesItem facilitiesItem : houseFacilitiesItems) {
            HouseInspectionFacility houseInspectionFacility = new HouseInspectionFacility();
            houseInspectionFacility.setOrderId(orderId);
            houseInspectionFacility.setHouseId(order.getHouseId());
            houseInspectionFacility.setFacilitiesName(facilitiesItem.getFacilitiesName());
            houseInspectionFacility.setFacilitiesPrice(facilitiesItem.getFacilitiesPrice());
            houseInspectionFacility.setFacilitiesState(facilitiesItem.getFacilitiesState());
            houseInspectionFacility.setFacilitiesId(facilitiesItem.getFacilitiesId());
            houseInspectionFacility.setCreateBy("System");
            houseInspectionFacility.setCreateTime(new Date());
            houseInspectionFacility.setInspectionStatus(HouseInspectionFacility.ORDER_STATE_USER_HOUSE_INSPECTION);
            houseInspectionFacilityMapper.insertHouseInspectionFacility(houseInspectionFacility);
        }

        HousingAllocation allocation = new HousingAllocation();
        allocation.setCleaningType(HousingAllocation.CLEANING_TYPE_NO);
        allocation.setAllocationId(order.getAllocationId());
        housingAllocationService.updateApartmentAllocation(allocation);

        //长租公寓  新增账单规则
        String houseId = order.getHouseId();
        HousingAllocation housingAllocation = housingAllocationService.selectHousingAllocationByHouseId(houseId);
        Integer apartmentType = housingAllocation.getApartmentType();
        Long payTypeId = housingAllocation.getPayTypeId();
        if (HousingAllocation.APARTMENT_TYPE_LONG.equals(apartmentType)) {
            Long orgId = order.getOrgId();
            Date checkInTime = order.getCheckInTime();
            Date checkOutTime = order.getCheckOutTime();
            ApartmentBillRule rule = new ApartmentBillRule();
            rule.setOrderId(orderId);
            rule.setOrgId(orgId);
            rule.setStartTime(checkInTime);
            rule.setEndTime(checkOutTime);
            rule.setBillLastTime(date);
            rule.setCreateTime(date);
            rule.setHouseId(order.getHouseId());
            rule.setReservationId(order.getReservationId());
            rule.setReservationName(order.getReservationName());
            rule.setReservationPhone(order.getReservationPhone());

            // 押付方式
            PayType payType = payTypeService.selectPayTypeById(payTypeId);
            Long payMonth = payType.getPayMonth();
            rule.setPayMonth(payMonth);

            //生成默认为一号生成 五号为缴费截止日期
            rule.setBillCreateDate(1);
            rule.setCloseTime(5);
            apartmentBillRuleService.insertApartmentBillRule(rule);
            Long ruleId = rule.getRuleId();
            //账单规则与收费项目关联
            List<ApartmentChargeItem> apartmentChargeItems = apartmentChargeItemService.selectApartmentChargeItemByOrgId(orgId);
            for (ApartmentChargeItem item : apartmentChargeItems) {
                ApartmentItemRuleRef ref = new ApartmentItemRuleRef();
                ref.setRuleId(ruleId);
                ref.setItemId(item.getItemId());
                ref.setItemType(ApartmentItemRuleRef.ITEM_TYPE_DEFAULT_ITEM);
                ref.setItemName(item.getItemName());
                ref.setItemUnit(item.getItemUnit());
                ref.setCreateTime(date);
                apartmentItemRuleRefService.insertApartmentItemRuleRef(ref);
            }
        }
        return AjaxResult.success();
    }


    /**
     * 退租
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    @Transactional
    public AjaxResult renunciation(String orderId) {

        //校验订单是否已申请退租
        if (!houseQuitLeaseService.checkOrderIdUnique(orderId)) {
            Integer code = Convert.toInt(StatusCode.ERROR_CODE_10001.getErrorCode());
            return AjaxResult.error(code, "订单已退租");
        }


        ApartmentBill apartmentBill = new ApartmentBill();
        apartmentBill.setOrderId(orderId);
        apartmentBill.setPayStatus(ApartmentBill.PAY_STATUS_NO);
        apartmentBill.setAuditStatus(ApartmentBill.BILL_AUDIT_STATUS_TRUE);
        List<ApartmentBill> apartmentBills = apartmentBillService.selectApartmentBillList(apartmentBill);
        if (CollectionUtil.isNotEmpty(apartmentBills)){
            Integer code = Convert.toInt(StatusCode.ERROR_CODE_10001.getErrorCode());
            return AjaxResult.error(code, "还有账单未支付,请先支付后退租！");
        }




        // 修改订单状态为已退租
        Order order = orderService.selectOrderById(orderId);
        Date date = new Date();
        if (!Order.ORDER_STATE_INSPECTION.equals(order.getOrderState())) {
            Integer code = Convert.toInt(StatusCode.ERROR_CODE_10001.getErrorCode());
            throw new BizException(code, "订单状态有误");
        }

        // 新增订单操作记录
        OrderOperatingRecord orderRecord = new OrderOperatingRecord();
        orderRecord.setOrderId(order.getOrderId());
        orderRecord.setOrderSourceState(order.getOrderState());
        orderRecord.setOrderState(Order.ORDER_STATE_UN_CHECK_OUT);
        orderRecord.setCreateBy("System");
        orderRecord.setCreateTime(date);
        orderRecord.setOperatingBy("System");
        orderRecord.setOperatingTime(date);
        orderRecord.setRemark("用户提前退租");

        order.setOrderState(Order.ORDER_STATE_UN_CHECK_OUT);
        order.setRealityCheckOutTime(date);
        orderService.updateOrder(order);
        orderOperatingRecordService.insertOrderOperatingRecord(orderRecord);

        HouseQuitLease lease = new HouseQuitLease();
        lease.setHouseId(order.getHouseId());
        lease.setTenantId(order.getReservationId());
        lease.setTenantName(order.getReservationName());
        lease.setTenantPhone(order.getReservationPhone());
        lease.setQuitLeaseStatus(HouseQuitLease.QUIT_LEASE_STATUS_HAVE_APPLIED);
        lease.setQuitLeaseType(HouseQuitLease.QUIT_LEASE_TYPE_ADVANCE_CHECK_OUT);
        lease.setOrderId(orderId);


        //长租公寓生成退租账单并删除账单生成规则
        String houseId = order.getHouseId();
        HousingAllocation housingAllocation = GsonUtil.toBean(order.getAllocationContent(), HousingAllocation.class);
        Integer apartmentType = housingAllocation.getApartmentType();
        if (HousingAllocation.APARTMENT_TYPE_LONG.equals(apartmentType)) {
            //生成退租账单
            apartmentBillService.createRentWithdrawalBill(orderId);

            //手动退租后删除账单生成规则
            apartmentBillRuleService.deleteApartmentBillRuleByOrderId(orderId);
        }


        int flag = houseQuitLeaseService.insertHouseQuitLease(lease);
        return flag > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    /**
     * 退租 定时任务
     */
    @Transactional
    public void surrenderRentTask(Integer apartmentType) {
        Date date = new Date();
        log.info("退租定时任务 start");
        if (apartmentType == null) {
            log.error("退租定时任务类型数据为空");
            return;
        }
        // 修改订单状态为已退租
        List<Order> orderList = orderService.selectOrderByOrderState(Order.ORDER_STATE_INSPECTION);
        if (CollectionUtil.isNotEmpty(orderList)) {
            for (Order order : orderList) {
                HousingAllocation housingAllocation = GsonUtil.toBean(order.getAllocationContent(), HousingAllocation.class);
                Date checkOutTime = order.getCheckOutTime();
                Integer orderApartmentType = housingAllocation.getApartmentType();
                if (apartmentType.equals(orderApartmentType)) {
                    if (date.getTime() > checkOutTime.getTime()) {
                        if (Order.ORDER_STATE_INSPECTION != order.getOrderState()) {
                            log.error("订单状态有误" + order.getOrderId() + "当前订单状态 :" + order.getOrderState());
                            continue;
                        }

                        // 新增订单操作记录
                        OrderOperatingRecord orderRecord = new OrderOperatingRecord();
                        orderRecord.setOrderId(order.getOrderId());
                        orderRecord.setOrderSourceState(order.getOrderState());
                        orderRecord.setOrderState(Order.ORDER_STATE_UN_CHECK_OUT);
                        orderRecord.setCreateBy("System");
                        orderRecord.setCreateTime(date);
                        orderRecord.setOperatingBy("System");
                        orderRecord.setOperatingTime(date);
                        orderRecord.setRemark("订单时间到期,系统自动退租");

                        order.setOrderState(Order.ORDER_STATE_UN_CHECK_OUT);
                        order.setRealityCheckOutTime(date);
                        orderService.updateOrder(order);
                        orderOperatingRecordService.insertOrderOperatingRecord(orderRecord);
                        // todo 查询未缴账单放入退租记录表

                        HouseQuitLease lease = new HouseQuitLease();
                        lease.setHouseId(order.getHouseId());
                        lease.setTenantId(order.getReservationId());
                        lease.setTenantName(order.getReservationName());
                        lease.setTenantPhone(order.getReservationPhone());
                        lease.setQuitLeaseStatus(HouseQuitLease.QUIT_LEASE_STATUS_HAVE_APPLIED);
                        lease.setQuitLeaseType(HouseQuitLease.QUIT_LEASE_TYPE_NORMAL_CHECK_OUT);
                        lease.setOrderId(order.getOrderId());
                        houseQuitLeaseService.insertHouseQuitLease(lease);


                        //长租公寓生成退租账单并删除账单生成规则
                        if (HousingAllocation.APARTMENT_TYPE_LONG.equals(apartmentType)) {
                            //生成退租账单
                            apartmentBillService.createRentWithdrawalBill(order.getOrderId());

                            //手动退租后删除账单生成规则
                            apartmentBillRuleService.deleteApartmentBillRuleByOrderId(order.getOrderId());
                        }


                        // 新增退房提醒 提示验房
                        AjaxResult result = subscribeService.sendHouseState(order.getOrderId());
                        if (ObjectUtil.isNotNull(result)) {
                            Integer code = Convert.toInt(result.get("code"));
                            if (500 == code) {
                                String msg = Convert.toStr(result.get("msg"));
                                log.error(msg);
                            }
                        } else {
                            log.error("退租验房订阅消息发送失败 订单id: " + order.getOrderId());
                        }
                    }
                }
            }
            log.info("退租定时任务 end");
        }
    }

    @Override
    public AjaxResult reletting(String orderId, String reletOrderId) {

        Date date = new Date();
        Order order = orderService.selectOrderById(orderId);
        if (ObjectUtil.isNull(order) || !order.getOrderState().equals(Order.ORDER_STATE_COMPLETION)) {
            Integer code = Convert.toInt(StatusCode.ERROR_CODE_10001.getErrorCode());
            throw new BizException(code, "订单异常");
        }
        Order reletOrder = orderService.selectOrderById(reletOrderId);
        if (ObjectUtil.isNull(reletOrder) || !reletOrder.getOrderState().equals(Order.ORDER_STATE_PAYMENT)) {
            Integer code = Convert.toInt(StatusCode.ERROR_CODE_10001.getErrorCode());
            throw new BizException(code, "订单异常");
        }

        List<HouseInspectionFacility> facilities = houseInspectionFacilityMapper.selectHouseInspectionFacilityByOrderId(orderId);
        if (CollectionUtil.isNotEmpty(facilities)) {
            facilities.forEach(m -> {
                m.setFacilitiesInspectionId(null);
                m.setOrderId(orderId);
                houseInspectionFacilityMapper.insertHouseInspectionFacility(m);
            });
        }

        HouseInspection houseInspection = houseInspectionService.selectHouseInspectionByOrderIdAndInspectionStatus(orderId, HouseInspection.ORDER_STATE_USER_HOUSE_INSPECTION);
        houseInspection.setOrderId(orderId);
        houseInspection.setInspectionId(null);
        houseInspectionService.insertHouseInspection(houseInspection);


        // 新增订单操作记录
        OrderOperatingRecord orderRecord = new OrderOperatingRecord();
        orderRecord.setOrderId(reletOrder.getOrderId());
        orderRecord.setOrderSourceState(reletOrder.getOrderState());
        orderRecord.setOrderState(Order.ORDER_STATE_INSPECTION);
        orderRecord.setCreateBy("System");
        orderRecord.setCreateTime(date);
        orderRecord.setOperatingBy("System");
        orderRecord.setOperatingTime(date);

        reletOrder.setOrderState(Order.ORDER_STATE_INSPECTION);
        reletOrder.setUpdateTime(date);

        orderService.updateOrder(reletOrder);
        orderOperatingRecordService.insertOrderOperatingRecord(orderRecord);


        // todo
        // 将未缴费账单继承至新订单

        return AjaxResult.success();
    }

}
